package com.powernode.aspect;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @author RenBoQing
 * @date 2024年07月21日 12:48
 * @Description 系统日志的切面 AOP
 */
@Component
@Aspect
@Slf4j
public class SysLogAspect {
    /*
    设置切入点表达式
    */
    public static final String POINT_CUT = "execution(* com.powernode.controller..*.*(..))";

    /*
     * 所有的渲染通知
     * @author RenBoQing
     * @date 2024/7/21 12:53
     * @param joinPoint
     * @return java.lang.Object
     */
    @Around(value = POINT_CUT)
    public Object LogAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = null;
        // 获取请求的对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        // 获取请求用户的IP地址
        String remoteHost = request.getRemoteAddr();
        // 获取请求的参数
        Object[] args = joinPoint.getArgs();
        // 获取请求的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String methodName = method.getName();
        // 获取目标方法上的 ApiOperation 注解
        ApiOperation apiOperation = method.getDeclaredAnnotation(ApiOperation.class);
        String operation = "";
        // 判断是否为空
        if (ObjectUtils.isNotEmpty(apiOperation)) {
            // 获取ApiOperation的描述
            operation = apiOperation.value();
        }
        // 判断 对应的参数是否为空 为文件上传
        String finalArgs = "";
        if (ObjectUtils.isNotEmpty(args) &&  args[0] instanceof MultipartFile) {
            // 获取对应的参数
            finalArgs = "file";
        } else {
            // 参数转为json
            finalArgs = JSONObject.toJSONString(args);
        }
        // 记录开始的时间
        long startTime = System.currentTimeMillis();
        // 执行对应的方法
        try {
            result = joinPoint.proceed(args);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        // 记录结束的时间
        long endTime = System.currentTimeMillis();
        // 执行方法的时长
        long execTime = endTime - startTime;
        log.info("请求的IP地址:{},请求的方法:{},请求的参数:{},请求的描述:{},请求的时长:{}", remoteHost, methodName, finalArgs, operation, execTime);
        return result;
    }
}
